/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.afkt.project.ui.widget.swipeaction;

import com.ohos.afkt.ResourceTable;
import ohos.aafwk.ability.Ability;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.*;
import ohos.agp.components.element.ShapeElement;
import ohos.multimodalinput.event.MmiPoint;
import ohos.multimodalinput.event.TouchEvent;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/** 滑动适配器 */
public class ContactAdapter extends RecycleItemProvider implements Component.TouchEventListener {
    private ArrayList<Contact> mData = new ArrayList<>();
    private int mLayoutId;
    private Ability mSlice;
    private int mViewWidth = 1; // 1而不是0以防止被零除
    private ListContainer mListContainer;
    private float mDownX;
    private float mDownY;
    private boolean mFadeOut = false; // 淡出
    private ContactCallbacks mCallbacks;
    private int mDownPosition;
    private SwipeDirection mDirection = SwipeDirection.DIRECTION_NEUTRAL;
    private boolean mFar;
    private float mFarSwipeFraction = 0.5f;
    private RgbColor mRgbColor = new RgbColor(255, 255, 255);

    /** 背景 */
    protected HashMap<SwipeDirection, RgbColor> mBackgroundResIds = new HashMap<>();

    public ContactAdapter(Ability abilitySlice, ArrayList<Contact> contacts, int layoutId, ListContainer listContainer, ContactCallbacks callbacks) {
        mSlice = abilitySlice;
        mData = contacts;
        mLayoutId = layoutId;
        mListContainer = listContainer;
        mCallbacks = callbacks;
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }


    @Override
    public Object getItem(int posotion) {
        return null;
    }

    @Override
    public int getCount() {
        return mData.size();
    }

    @Override
    public Component getComponent(int position, Component convertView, ComponentContainer parent) {
        Component component = LayoutScatter.getInstance(mSlice).parse(mLayoutId, null, false);
        if (!(component instanceof ComponentContainer)) {
            return null;
        }

        ComponentContainer rootLayout = (ComponentContainer) component;
        Text tvIndex = (Text) rootLayout.findComponentById(ResourceTable.Id_text);
        tvIndex.setText(mData.get(position).getIndex());
        // 设置TouchEvent监听
        component.setTouchEventListener(this::onTouchEvent);
        return component;
    }

    @Override
    public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
        if (mViewWidth < 2) {
            mViewWidth = component.getWidth();
        }
        MmiPoint point = touchEvent.getPointerPosition(touchEvent.getIndex());
        float eventY = point.getY();
        float eventX = point.getX();
        if (eventX < 0) {
            eventX = 0;
        } else if (eventX > mViewWidth) {
            eventX = mViewWidth;
        }
        switch (touchEvent.getAction()) {
            case TouchEvent.PRIMARY_POINT_DOWN: {
                mDownY = eventY;
                mDownX = eventX;
                return true;
            }

            case TouchEvent.CANCEL: {
                if (mCallbacks != null) {
                    mCallbacks.onSwipe(mDownPosition, mDirection);
                }
                if (mCallbacks != null) {
                    mCallbacks.shouldDismiss(mDownPosition, mDirection);
                }
                mDownPosition = ListContainer.INVALID_INDEX;
                mDirection = SwipeDirection.DIRECTION_NEUTRAL;
                component.setTranslationX(0);
                component.invalidate();
                break;
            }

            case TouchEvent.PRIMARY_POINT_UP: {
                if (mCallbacks != null) {
                    mCallbacks.onSwipeEnded(mListContainer, mDownPosition, mDirection);
                }
                if (mCallbacks != null) {
                    mCallbacks.onSwipe(mDownPosition, mDirection);
                }
                if (mCallbacks != null) {
                    mCallbacks.shouldDismiss(mDownPosition, mDirection);
                }
                mDownPosition = ListContainer.INVALID_INDEX;
                mDirection = SwipeDirection.DIRECTION_NEUTRAL;
                component.setTranslationX(0);
                component.invalidate();
                break;
            }

            case TouchEvent.POINT_MOVE: {
                if (mDownY - eventY > 10 || mDownY - eventY < -10) {
                    break;
                }
                if (mCallbacks != null) {
                    mCallbacks.onSwipeStarted(mListContainer, mDownPosition, mDirection);
                }
                float deltaX = eventX - mDownX;
                if (mDirection.isLeft() && deltaX > 0 || mDirection.isRight() && deltaX < 0) {
                    mFar = false;
                }
                if (!mFar && Math.abs(deltaX) > mViewWidth * mFarSwipeFraction) {
                    mFar = true;
                }
                if (!mFar){
                    mDirection = (deltaX > 0 ? SwipeDirection.DIRECTION_NORMAL_RIGHT : SwipeDirection.DIRECTION_NORMAL_LEFT);
                } else {
                    mDirection = (deltaX > 0 ? SwipeDirection.DIRECTION_FAR_RIGHT : SwipeDirection.DIRECTION_FAR_LEFT);
                }
                if (mCallbacks != null) {
                    if (mCallbacks.hasActions(mDownPosition, mDirection)) {
                        mListContainer.setTouchFocusable(true);
                        ShapeElement element = new ShapeElement();
                        for (Map.Entry<SwipeDirection, RgbColor> entry : mBackgroundResIds.entrySet()) {
                            if (entry.getKey().equals(SwipeDirection.DIRECTION_NORMAL_LEFT) && eventX < mViewWidth / 4) {
                                mRgbColor = entry.getValue();
                            } else if (entry.getKey().equals(SwipeDirection.DIRECTION_FAR_LEFT) && eventX >= mViewWidth / 4 && eventX < mViewWidth / 2) {
                                mRgbColor = entry.getValue();
                            } else if (entry.getKey().equals(SwipeDirection.DIRECTION_NORMAL_RIGHT) && eventX >= mViewWidth / 2 && eventX < mViewWidth * 3 / 4) {
                                mRgbColor = entry.getValue();
                            } else if (entry.getKey().equals(SwipeDirection.DIRECTION_FAR_RIGHT) && eventX >= mViewWidth * 3 / 4 & eventX <= mViewWidth) {
                                mRgbColor = entry.getValue();
                            }
                        }
                        element.setRgbColor(mRgbColor);
                        mListContainer.setBackground(element);
                        if (mDownX < (mViewWidth / 2)) {
                            component.setTranslationX(eventX);
                            // 设置透明度
                            if (mFadeOut) {
                                component.setAlpha(Math.max(0, Math.min(1, 1 - 2 * Math.abs(deltaX) / mViewWidth)));
                            }
                        } else {
                            component.setTranslationX(eventX - mViewWidth);
                        }
                        component.setTranslationY(0);
                        component.invalidate();
                    }
                }
                return true;
            }
        }
        return true;
    }

    /**
     *  添加背景
     *
     * @param key type
     * @param color 颜色
     * @return ContactAdapter
     */
    public ContactAdapter addBackground(SwipeDirection key, RgbColor color) {
        if (SwipeDirection.getAllDirections().contains(key)) {
            mBackgroundResIds.put(key, color);
        }
        return this;
    }

    /** item的回调 */
    public interface ContactCallbacks {
        boolean hasActions(int position, SwipeDirection direction);

        boolean shouldDismiss(int position, SwipeDirection direction);

        void onSwipe(int position, SwipeDirection direction);

        @SuppressWarnings("unused")
        default void onSwipeStarted(ListContainer listView, int position, SwipeDirection direction) {
        }

        ;

        @SuppressWarnings("unused")
        default void onSwipeEnded(ListContainer listView, int position, SwipeDirection direction) {
        }

        ;
    }
}
